package com.ct.application.order.service;

import com.google.common.util.concurrent.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class OrderService  {


//    @Autowired
//    private ApplicationContext applicationContext;
    ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
//    @Autowired
//    private OrderAsyncService orderAsyncService;
    //private ExecutorService executorService = Executors.newCachedThreadPool();

    // 1:我想获取发送短信和获取积分的执行结果?
    // 2:耦合代码
    // 3:如果线程执行失败或者出现故障如何处理
    // 4:性能问题

    @Transactional(rollbackFor = Exception.class)
    public boolean makeOrder(Long userId, Long productId) throws ExecutionException, InterruptedException {
        log.info("用户：{}，下单产品ID是：{},并扣减库存", userId, productId);
//        第一种方式：使用thread的方式
//        new SendMsgThread(userId).start();
//        new ScoreGetThread(userId).start();
//        第二种方式：实现Runnable接口
//        SendMsgRunnable sendMsgRunnable = new SendMsgRunnable(userId);
//        ScoreGetThread scoreGetThread = new ScoreGetThread(userId);
//        new Thread(sendMsgRunnable).start();
//        new Thread(scoreGetThread).start();
//
//        第三种解决方案: 线程池 + future / task机制
//        SendMsgRunnable sendMsgRunnable = new SendMsgRunnable(userId);
//        ScoreGetThread scoreGetThread = new ScoreGetThread(userId);
//        Future<?> submit1 = executorService.submit(sendMsgRunnable);
//        Future<?> submit2 = executorService.submit(scoreGetThread);
//        System.out.println(submit1.get());
//        System.out.println(submit2.get());
//
//        SendMsgRunnable sendMsgRunnable = new SendMsgRunnable(userId);
//        ScoreGetThread scoreGetThread = new ScoreGetThread(userId);
//        Future<?> submit1 = executorService.submit(() -> {
//            log.info("赠送积分成功，用户是：{}", userId);
//        });
//        Future<?> submit2 = executorService.submit(() -> {
//            log.info("发消息订单下单成功，用户是：{}", userId);
//        });
//        System.out.println(submit1.get());
//        System.out.println(submit2.get());
//
//        第四种解决方案:  线程池 + future / task机制 + 返回值
//
//        Future<Boolean> submit1 = executorService.submit(() -> {
//            log.info("赠送积分成功，用户是：{}", userId);
//            return true;
//        });
//
//        Future<Boolean> submit2 = executorService.submit(() -> {
//            log.info("发消息订单下单成功，用户是：{}", userId);
//            return true;
//        });
//
//        System.out.println(submit1.get());
//        System.out.println(submit2.get());
//
//
//        第五种解决方案:  线程池 + fork / join机制, 内部线程池：ForkJoinPool
//        CompletableFuture<Boolean> submit1 = CompletableFuture.supplyAsync(() -> {
//            log.info("赠送积分成功，用户是：{}", userId);
//            return true;
//        });
//        CompletableFuture<Boolean> submit2 = CompletableFuture.supplyAsync(() -> {
//            log.info("发消息订单下单成功，用户是：{}", userId);
//            return true;
//        });
//        System.out.println(submit1.get());
//        System.out.println(submit2.get());


        // 第六种方式：springboot +@Async
//        orderAsyncService.sendMessage(userId);
//        orderAsyncService.socreGet(userId);
        // 第七种方式：spring的事件监听机制
        //applicationContext.publishEvent(new OrderEvent(userId));
        // 第八种方式：guava异步线程处理
        final ListenableFuture<Integer> listenableFuture = executorService.submit(new Callable<Integer>() {
              @Override
              public Integer call() throws Exception {
                  log.info("callable execute...");
                  TimeUnit.SECONDS.sleep(1);
                  return 1;
              }
         });

        Futures.addCallback(listenableFuture, new FutureCallback<Integer>() {
            @Override
            public void onSuccess(Integer result) {
                //成功执行...
                System.out.println("Get listenable future's result with callback " + result);
            }

            @Override
            public void onFailure(Throwable t) {
                //异常情况处理...
                t.printStackTrace();
            }
        });

        Integer i = listenableFuture.get();

        return true;
    }
}
